package com.iteaj.iot.plc.omron;

import com.iteaj.iot.plc.PLCUtils;
import com.iteaj.iot.plc.PlcAddressResolver;
import com.iteaj.iot.plc.PlcException;
import com.iteaj.iot.plc.PlcProtocolType;

import java.util.Locale;

/**
 * 欧姆龙读写操作地址解析
 */
public class OmronAddressResolver extends PlcAddressResolver {

    /**
     * 获取位操作指令
     * @return 位操作指令
     */
    public byte getBitCode() {
        return BitCode;
    }

    /**
     * 设置位操作的指令
     * @param bitCode 位操作指令
     */
    public void setBitCode(byte bitCode) {
        BitCode = bitCode;
    }

    /**
     * 获取字操作的指令
     * @return 字操作指令
     */
    public byte getWordCode() {
        return WordCode;
    }

    /**
     * 设置字操作指令
     * @param wordCode 字操作指令
     */
    public void setWordCode(byte wordCode) {
        WordCode = wordCode;
    }

    private byte BitCode = 0;
    private byte WordCode = 0;

    private static int CalculateBitIndex( String address ) {
        String[] splits = address.split("\\.");
        int addr = Integer.parseInt(splits[0]) * 16;
        // 包含位的情况，例如 D100.F
        if (splits.length > 1) {
            addr += PLCUtils.calculateBitStartIndex(splits[1]);
        }
        return addr;
    }

    /**
     * 从实际的欧姆龙的地址里面解析出地址对象<br />
     * @param address 欧姆龙的地址数据信息
     * @return 是否成功的结果对象
     */
    public static OmronAddressResolver ParseFrom( String address ) {
        return ParseFrom(address, (short) 0);
    }

    /**
     * 从实际的欧姆龙的地址里面解析出地址对象<br />
     * @param address 欧姆龙的地址数据信息
     * @param length 读取的数据长度
     * @return 是否成功的结果对象
     */
    public static OmronAddressResolver ParseFrom( String address, short length ) {
        OmronAddressResolver addressData = new OmronAddressResolver();
        try {
            addressData.setLength(length);
            String tempAddress = address.toUpperCase(Locale.ROOT);
            if (tempAddress.startsWith("DR")) {
                addressData.setWordCode((byte) 0xBC);  // CV Mode 为 9C
                addressData.setAddressStart(CalculateBitIndex( address.substring( 2 ) ) + 0x200 * 16);
            } else if (tempAddress.startsWith("IR")) {
                addressData.setWordCode( (byte) 0xDC);
                addressData.setAddressStart(CalculateBitIndex( address.substring( 2 ) ) + 0x100 * 16);
            } else if (tempAddress.startsWith("DM")) {
                // DM区数据
                addressData.BitCode      = OmronFinsModel.DM.getBit();
                addressData.WordCode     = OmronFinsModel.DM.getWord();
                addressData.setAddressStart(CalculateBitIndex( address.substring( 2 ) ));
            } else if (tempAddress.startsWith("TIM")) {
                addressData.BitCode      = OmronFinsModel.TIM.getBit();
                addressData.WordCode     = OmronFinsModel.TIM.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 3 ) ));
            } else if (tempAddress.startsWith("CNT")) {
                addressData.BitCode      = OmronFinsModel.TIM.getBit();
                addressData.WordCode     = OmronFinsModel.TIM.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 3 ) ) + 0x8000 * 16);
            } else if (tempAddress.startsWith("CIO")) {
                addressData.BitCode      = OmronFinsModel.CIO.getBit();
                addressData.WordCode     = OmronFinsModel.CIO.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 3 ) ));
            } else if (tempAddress.startsWith("WR")){
                addressData.BitCode      = OmronFinsModel.WR.getBit();
                addressData.WordCode     = OmronFinsModel.WR.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 2 ) ));
            }else if (tempAddress.startsWith("HR")){
                addressData.BitCode      = OmronFinsModel.HR.getBit();
                addressData.WordCode     = OmronFinsModel.HR.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 2 ) ));
            }else if (tempAddress.startsWith("AR")){
                addressData.BitCode      = OmronFinsModel.AR.getBit();
                addressData.WordCode     = OmronFinsModel.AR.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 2 ) ));
            }else if (tempAddress.startsWith("CF")){
                addressData.BitCode = 0x07;
                addressData.setAddressStart( CalculateBitIndex( address.substring( 2 ) ));
            }else if (tempAddress.startsWith( "EM" ) || tempAddress.startsWith("E")){
                // E区，比较复杂，需要专门的计算
                String[] splits = address.split( "\\." );
                int block = Integer.parseInt( splits[0].substring( (tempAddress.charAt(1) == 'M') ? 2 : 1 ), 16 );
                if (block < 16){
                    addressData.BitCode  = (byte)(0x20 + block);
                    addressData.WordCode = (byte)(0xA0 + block);
                }else {
                    addressData.BitCode  = (byte)(0xE0 + block - 16);
                    addressData.WordCode = (byte)(0x60 + block - 16);
                }
                addressData.setAddressStart( CalculateBitIndex( address.substring( address.indexOf( '.' ) + 1 ) ));
            } else if (tempAddress.startsWith("D")) {
                // DM区数据
                addressData.BitCode      = OmronFinsModel.DM.getBit();
                addressData.WordCode     = OmronFinsModel.DM.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 1 ) ));
            } else if (tempAddress.startsWith("C")) {
                addressData.BitCode      = OmronFinsModel.CIO.getBit();
                addressData.WordCode     = OmronFinsModel.CIO.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 1 ) ));
            } else if (tempAddress.startsWith("W")) {
                addressData.BitCode      = OmronFinsModel.WR.getBit();
                addressData.WordCode     = OmronFinsModel.WR.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 1 ) ));
            } else if (tempAddress.startsWith("H")) {
                addressData.BitCode      = OmronFinsModel.HR.getBit();
                addressData.WordCode     = OmronFinsModel.HR.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 1 ) ));
            } else if (tempAddress.startsWith("A")) {
                addressData.BitCode      = OmronFinsModel.AR.getBit();
                addressData.WordCode     = OmronFinsModel.AR.getWord();
                addressData.setAddressStart( CalculateBitIndex( address.substring( 1 ) ));
            } else {
                throw new PlcException("Omron不支持的地址["+address+"]");
            }

        } catch (Exception ex) {
            throw new PlcException(ex.getMessage(), ex, PlcProtocolType.Omron);
        }

        return addressData;
    }
}
